package com.it.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.it.reggie.common.BaseContext;
import com.it.reggie.common.CustomException;
import com.it.reggie.entity.*;
import com.it.reggie.mapper.OrderMapper;
import com.it.reggie.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService{

    @Autowired
    private ShoppingCartService shoppingCartService;

    @Autowired
    private UserService userService;

    @Autowired
    private AddressBookService addressBookService;

    @Autowired
    private OrderDetailService orderDetailService;

    @Override//下单
    @Transactional//操作多个表。。。要么全成功
    public void submit(Orders orders) {//下单时要知道用户id是谁,而提交过来的数据并没有用户id
        //当前用户id
        Long userId = BaseContext.getCurrentId();
        //拿id去查询当前用户的购物车数据(有那些菜品，套餐)
        LambdaQueryWrapper<ShoppingCart> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ShoppingCart::getUserId,userId);
        List<ShoppingCart> shoppingCarts =shoppingCartService.list(wrapper);
        //假设购物车是空的，就不能下单
        if(shoppingCarts ==null || shoppingCarts.size() == 0){
            throw new CustomException("购物车为空不能下单1");//抛出自定义异常
        }//订单表里需要使用到用户地址手机号等信息。。需要用userId来查出来(地址表，用户表)
        //查用户数据
        User user = userService.getById(userId);
        //查地址数据,点击去支付的时候，已经把addresssBookId传过来了(传进orders参数里面了)
        Long addressBookId = orders.getAddressBookId();
        AddressBook addressBook = addressBookService.getById(addressBookId);
        if(addressBook ==null){
            throw new CustomException("请先填写地址");//抛出自定义异常
        }

        //把属性填充完整再保存,orders里有id(主键值),number(订单号),status(订单状态),userId。。。。除了addressbookId，payMethod,remark这三个已经提交过来的之外
        long orderId = IdWorker.getId();//‘IdWorker’是框架提供的用于生成唯一ID的实用程序类。它用于生成基于雪花算法的64位长类型ID。生成的ID由时间戳、工人ID和序列号组成，即使在分布式系
// 统中也能确保唯一性。您可以在MyBatis-Plus中使用'IdWorker'，方法是导入必要的依赖项并调用其'getId（）'方法来为您的实体或对象生成ID。然后可以将这些生成的ID用作数据库表中的主键或唯一标识符。

        AtomicInteger amount = new AtomicInteger(0);//使用“AtomicInteger”，您可以原子地对整数值执行操作，
//这意味着这些操作是不可分割的，并且不能被其他线程中断。这确保了数据的一致性，避免了多个线程并发访问或修改“amount”变量时的冲突。（用int可能错误）
        List<OrderDetail> orderDetails = shoppingCarts.stream().map((item) -> {//每一次遍历出来的是一个购物车对象(装菜品或套餐)
//遍历shoppingCarts过程中，除了要计算总金额，还要把订单明细数据封装出来
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderId);//关联订单编号
            orderDetail.setNumber(item.getNumber());//份数
            orderDetail.setDishFlavor(item.getDishFlavor());
            orderDetail.setDishId(item.getDishId());
            orderDetail.setSetmealId(item.getSetmealId());
            orderDetail.setName(item.getName());
            orderDetail.setImage(item.getImage());
            orderDetail.setAmount(item.getAmount());//单份金额
//将“addAndGet（）”方法在对象上被调用（假设它是“AtomicInteger”的一个实例）将“intValue（）”的结果作为参数传递。此方法将指定的值添加到对象的当前值，并返回更新后的值。
            amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());
            return orderDetail;//    单价         *          ??           份数           转成int类型，算出一种菜品或套餐总价，累加到外面的amount变量里
        }).collect(Collectors.toList());//list批量保存订单明细

        orders.setNumber(String.valueOf(orderId));//生成orderId之后，设置给orders//类型转换
        orders.setId(orderId);
        orders.setOrderTime(LocalDateTime.now());
        orders.setCheckoutTime(LocalDateTime.now());//支付时间随便来一个
        orders.setStatus(2);//1：待付款，2：待派送，3：已派送，4：已完成，5：已取消
        orders.setAmount(new BigDecimal(amount.get()));//总金额//遍历购物车的商品，加起来
        orders.setUserId(userId);
        orders.setUserName(user.getName());
        orders.setConsignee(addressBook.getConsignee());//收货人在addressbook里
        orders.setPhone(addressBook.getPhone());
        orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
                + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
                + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())//省市区
                + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));//详细地址，门牌。。。
// 下单就是向订单表(order)，插入数据(都浓缩成一条数据)
        this.save(orders);
        //向订单明细表(orderDetail),插入数据(多条数据)(每一个菜品都有详细信息)
        orderDetailService.saveBatch(orderDetails);

        //下单成功，清空购物车数据(已经不需要了)
        shoppingCartService.remove(wrapper);//删除的时候还是可以使用42行的wrapper
    }
}